﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using PivotData;
using PivotWebsite.Controllers;
using PivotWebsite.MediaFormatters;
using System;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Hosting;

namespace PivotWebsite.Tests.Controllers
{
    [TestClass]
    [DeploymentItem("test.png")]
    public class ImagesControllerTest
    {
        [TestInitialize]
        public void TestReset()
        {
            Utils.TestInit();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            Utils.TestFinalize();
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void TestBadCollectionId()
        {
            var ic = new ImagesController();
            ic.PutImage(1, "fork", Utils.GetPng());
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void GetNoImagesBad()
        {
            var ic = new ImagesController();
            var images = ic.GetImages(5);
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void GetNoImageBadCollection()
        {
            var ic = new ImagesController();
            var images = ic.GetImage(5, 3);
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void GetNoImageBadImage()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var images = ic.GetImage(info.Id, 3);
        }

        [TestMethod]
        public void DeleteCollectionReallyGone()
        {
            var tc = new CollectionsController();
            var p1 = tc.PutCollection("hi");

            var ic = new ImagesController();
            ic.PutImage(p1.Id, "dude", Utils.GetPng());

            tc.DeleteCollection(p1.Id);

            var p2 = tc.PutCollection("fork");
            Assert.AreEqual(p1.Id, p2.Id, "Test failed b/c the id's didn't match");

            var img = ic.GetImages(p2.Id);
            Assert.AreEqual(0, img.Length, "No images inserted, shoudl be zero!");
        }

        [TestMethod]
        public void GetNoImages()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var images = ic.GetImages(info.Id);
            Assert.AreEqual(0, images.Length, "no images");
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void GetNoImageBad()
        {
            var ic = new ImagesController();
            var images = ic.GetImages(5);
        }

        [TestMethod]
        public void TestPutImage()
        {
            var cc = new CollectionsController();

            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            ic.Request = new HttpRequestMessage();
            var cfg = new HttpConfiguration();
            cfg.Formatters.Insert(0, new ImageFormatter());
            ic.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, cfg);

            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork", inputData);

            Assert.IsNotNull(img, "image datastructure");
            var images = ic.GetImages(info.Id);
            Assert.AreEqual(1, images.Length, "1 image in there");
            Assert.AreEqual("fork", images[0].Name, "name is incorrect");
            Assert.IsTrue(img.Id == images[0].Id, "id's should be identical");

            // Make sure we can get back the correct image data now.
            var outputDataMessage = ic.GetImage(info.Id, img.Id);
            Assert.IsNotNull(outputDataMessage, "result message");
            Assert.IsNotNull(outputDataMessage.Content, "content");
            ImageFormatter.BinaryImage outputData;
            outputDataMessage.TryGetContentValue(out outputData);
            Assert.IsNotNull(outputData, "output data");

            Assert.AreEqual(inputData.metaData, outputData.metaData, "metadata incorrect");
            Assert.AreEqual(inputData.data.Length, outputData.data.Length, "data length incorrect");

            foreach (var b in inputData.data.Zip(outputData.data, (b1, b2) => Tuple.Create(b1, b2)))
            {
                Assert.AreEqual(b.Item1, b.Item2, "bytes not the same");
            }
        }

        [TestMethod]
        public void TestPut2Image()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork", inputData);
            var img1 = ic.PutImage(info.Id, "forkme", inputData);

            Assert.IsNotNull(img, "image datastructure");
            var images = ic.GetImages(info.Id);
            Assert.AreEqual(2, images.Length, "2?? image in there");
        }

        [TestMethod]
        public void TestPutSameImageTwice()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork", inputData);
            var img1 = ic.PutImage(info.Id, "fork", inputData);

            Assert.IsTrue(img.Id == img1.Id, "image id's should be same");

            var images = ic.GetImages(info.Id);
            Assert.AreEqual(1, images.Length, "1 image in there");
        }

        [TestMethod]
        public void TestGetImagesSimple()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork1", inputData);
            var img1 = ic.PutImage(info.Id, "fork2", inputData);

            var ifind = ic.GetImages(info.Id, "fork1");
            Assert.IsNotNull(ifind);
            Assert.AreEqual(1, ifind.Length);
            Assert.AreEqual(img.Id, ifind[0].Id);
        }

        [TestMethod]
        public void TestGetImagesNotThere()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork1", inputData);
            var img1 = ic.PutImage(info.Id, "fork2", inputData);

            var ifind = ic.GetImages(info.Id, "fork12");
            Assert.IsNotNull(ifind);
            Assert.AreEqual(0, ifind.Length);
        }

        [TestMethod]
        public void TestGetImagesWild()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork1", inputData);
            var img1 = ic.PutImage(info.Id, "fork2", inputData);

            var ifind = ic.GetImages(info.Id, "fork.*");
            Assert.IsNotNull(ifind);
            Assert.AreEqual(2, ifind.Length);
        }

        [TestMethod]
        [ExpectedException(typeof(HttpResponseException))]
        public void TestGetImagesBadcID()
        {
            var ic = new ImagesController();
            var ifind = ic.GetImages(3, "fork.*");
        }

        [TestMethod]
        public void TestGetImagesNoFacets()
        {
            var cc = new CollectionsController();
            var info = cc.PutCollection("fork");
            var ic = new ImagesController();
            var inputData = Utils.GetPng();
            var img = ic.PutImage(info.Id, "fork1", inputData);
            var fc = new FacetsController();
            fc.PutFacet(info.Id, img.Id, new PivotData.FacetAbsBase[] { new FacetString() { Name = "first", Value = "test" } });

            var imgdata = ic.GetImages(info.Id);
            Assert.IsNull(imgdata[0].Facets, "facets aren't null");

            imgdata = ic.GetImages(info.Id, true);
            Assert.IsNotNull(imgdata[0].Facets, "facets are null");
        }
    }
}
